package com.ruoyi.system.userController;

import com.alibaba.fastjson2.JSONObject;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.teaopenapi.models.Config;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.info.domain.FhInfoUser;
import com.ruoyi.info.service.IFhInfoUserService;
import com.ruoyi.system.domain.FhUser;
import com.ruoyi.system.domain.FhUserDto;
import com.ruoyi.system.domain.UserIdToken;
import com.ruoyi.system.service.IFhUserService;
import com.ruoyi.system.service.ISysMenuService;
import com.ruoyi.tools.IsPhoneNumber;
import com.ruoyi.tools.MD5;
import com.ruoyi.tools.YouMengToken;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import okhttp3.*;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

import static com.alibaba.fastjson2.JSON.toJSONString;

/**
 * 注册登录
 *
 * @author ruoyi
 */
//读取application.yml文件
@PropertySource("classpath:application.yml")
@Api(tags = "登录注册")
@RestController
public class UserRegisterLoginController {
    //获取过期时间
    @Value("${token.expireTime}")
    private Long expireTime;

    @Value("${hxim.appkey}")
    private String appkey;

    @Value("${hxim.ClientID}")
    private String ClientID;

    @Value("${hxim.ClientSecret}")
    private String clientSecret;

    @Value("${hxim.OrgName}")
    private String OrgName;

    @Value("${hxim.AppName}")
    private String appName;

    @Value("${hxim.AdminToken}")
    private String AdminToken;


    @Autowired
    private SysLoginService loginService;

    @Autowired
    private ISysMenuService menuService;

    @Autowired
    private SysPermissionService permissionService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private IFhUserService iFhUserService;

    @Autowired
    private IFhInfoUserService fhInfoUserService;

    @Autowired  //注入
    StringRedisTemplate stringRedisTemplate;


    // 导入redis配置
    @Autowired
    @Qualifier("stringRedisTemplate")
    RedisTemplate<String, String> rt;

    /**
     * 获取验证码
     *
     * @param phone 手机号码
     * @return 结果
     */
    @ApiOperation("获取验证码")
    @Anonymous
    @PostMapping("/userCode")
    public R<String> getCode(String phone) throws Exception {
        if (phone == null) {
            return R.fail("手机号为空");
        }
        String code = String.valueOf(ThreadLocalRandom.current().nextInt(100000, 1000000));
        System.out.println(code);
        //取出验证码,验证码若存在，不允许发送
        ValueOperations<String, String> Value = rt.opsForValue();
        String old_cts = Value.get(phone + "_cts");
        if (old_cts != null) {
            return R.fail("1分钟内只允许发送一次");
        }
        //将验证码存储到redis中,设置时间为5分钟
        ValueOperations forValue = rt.opsForValue();
        forValue.set(phone + "_yzm", code);
        rt.expire(phone + "_yzm", 300 * 1000, TimeUnit.MILLISECONDS);

        //验证码发送间隔1分钟
        ValueOperations codeTimeSend = rt.opsForValue();
        codeTimeSend.set(phone + "_cts", code);
        rt.expire(phone + "_cts", 60 * 1000, TimeUnit.MILLISECONDS);

        //发送验证码
//        sendMsg(phone,code);
        return R.ok(code);
    }

    /**
     * 注册
     *
     * @param fhUserDto 注册信息
     * @return 结果
     */
    @ApiOperation("用户注册")
    @Anonymous
    @PostMapping("/userRegister")
    public R rgister(FhUserDto fhUserDto) {
        String phone = fhUserDto.getPhone();
        String code = fhUserDto.getCode();
        //取出验证码
        ValueOperations<String, String> Value = rt.opsForValue();
        String old_yzm = Value.get(phone + "_yzm");
        if (old_yzm == null) {
            return R.fail("验证码不存在或者过期");
        } else if (old_yzm.equals(code)) {
            System.out.println("验证码正确");
            //根据手机号,用户名查询是否存在该用户
            FhUser fhUser1 = new FhUser();
            fhUser1.setPhone(fhUserDto.getPhone());
            List<FhUser> fhUsers = iFhUserService.selectFhUserList(fhUser1);
            if (!fhUsers.isEmpty()) {
                return R.fail("该手机或用户名已注册账户");
            }
            //注册该用户
            FhUser fhUser = new FhUser();
            BeanUtils.copyProperties(fhUserDto, fhUser);
            //加密密码
            MD5 md5 = new MD5();
            fhUser.setPassword(md5.encode(fhUser.getPassword()));
            int i = iFhUserService.insertFhUser(fhUser);
            if (i > 0) {
                return R.ok("注册成功");
            }
            return R.fail("注册失败");
        }
        return R.fail("验证码错误");
    }

    /**
     * 账号密码登录方法
     *
     * @param fhUser 登录信息
     * @return 结果
     */
    @PostMapping("/userLogin")
    @ApiOperation("账号密码登录")
    @Anonymous
    public R<UserIdToken> login(FhUser fhUser) throws IOException {
        if (fhUser.getAccountOrPhone() == null || fhUser.getPassword() == null) {
            return R.fail("账号或者密码不能为空");
        }
        MD5 md5 = new MD5();
        //判断是否为手机号
        IsPhoneNumber isValidPhoneNumber = new IsPhoneNumber();
        boolean isPhone = isValidPhoneNumber.isValidPhoneNumber(fhUser.getAccountOrPhone());
        if (isPhone) {
            //手机号密码查询
            FhUser fhUser1 = new FhUser();
            fhUser1.setPhone(fhUser.getAccountOrPhone());
            fhUser1.setPassword(md5.encode(fhUser.getPassword()));
            List<FhUser> fhUsersByPhone = iFhUserService.selectFhUserList(fhUser1);
            if (!fhUsersByPhone.isEmpty()) {
                //手机号登录
                // 生成令牌
                String token = loginService.userlogin(fhUsersByPhone.get(0).getId(), fhUsersByPhone.get(0).getAccount(), fhUser.getPassword());
                //将token存储到redis中,设置时间为10000分钟
                ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
                ops.set(fhUsersByPhone.get(0).getAccount() + "_token", token, expireTime, TimeUnit.MINUTES);

                //查询用户信息表是否存在该用户，不存在则为新用户，返回false
                FhInfoUser fhInfoUser = new FhInfoUser();
                fhInfoUser.setUserId(fhUsersByPhone.get(0).getId());
                List<FhInfoUser> fhInfoUsers = fhInfoUserService.selectFhInfoUserList(fhInfoUser);
                Boolean isNew = false;
                if (fhInfoUsers.isEmpty()) {
                    isNew = true;
                }
                //获取imToken
                String imUserToken = getImUserToken(fhUsersByPhone.get(0).getId());
                JSONObject jsonObject = JSONObject.parseObject(imUserToken);
                String imToken =(String) jsonObject.get("access_token");
                UserIdToken userIdToken = new UserIdToken(isNew, token,imToken);
                return R.ok(userIdToken);
            }
            return R.fail("账号密码错误");
        } else {
            //账号密码查询
            FhUser fhUser2 = new FhUser();
            fhUser2.setAccount(fhUser.getAccountOrPhone());
            fhUser2.setPassword(md5.encode(fhUser.getPassword()));
            List<FhUser> fhUsersByAccount = iFhUserService.selectFhUserList(fhUser2);
            if (!fhUsersByAccount.isEmpty()) {
                //账号密码登录
                String token = loginService.userlogin(fhUser.getId(), fhUser.getAccount(), fhUser.getPassword());
                //将token存储到redis中,设置时间为10000分钟
                ValueOperations forValue = rt.opsForValue();
                forValue.set(fhUser.getAccount() + "_token", token);
                rt.expire(fhUsersByAccount.get(0).getAccount() + "_token", 600000 * 1000, TimeUnit.MILLISECONDS);

                //查询用户信息表是否存在该用户，不存在则为新用户，返回false
                FhInfoUser fhInfoUser = new FhInfoUser();
                fhInfoUser.setUserId(fhUsersByAccount.get(0).getId());
                List<FhInfoUser> fhInfoUsers = fhInfoUserService.selectFhInfoUserList(fhInfoUser);
                Boolean isNew = false;
                if (fhInfoUsers.isEmpty()) {
                    isNew = true;
                }
                //获取imToken
                String imUserToken = getImUserToken(fhUsersByAccount.get(0).getId());
                JSONObject jsonObject = JSONObject.parseObject(imUserToken);
                String imToken =(String) jsonObject.get("access_token");
                UserIdToken userIdToken = new UserIdToken(isNew, token,imToken);
                return R.ok(userIdToken);
            }
            return R.fail("账号密码错误");
        }

    }

    //发送短信sendMsg
    public void sendMsg(String phone, String code) throws Exception {
        Config config = new Config()
                // 配置 AccessKey ID，
                .setAccessKeyId("LTAI5tEyCsQK4SUXFWDAsVEM")
                // 配置 AccessKey Secret，
                .setAccessKeySecret("gch51qBnNZbp1a3SsmwYtW5J35nrDF");
        // 配置 Endpoint
        config.endpoint = "dysmsapi.aliyuncs.com";
        Client client = new Client(config);
        // 构造请求对象，请填入请求参数值
        SendSmsRequest sendSmsRequest = new SendSmsRequest()
                //发送手机号
                .setPhoneNumbers(phone)
                //短信签名-可在短信控制台找到
                .setSignName("南昌小智匠科技")
                //短信模板-可在短信控制台找到
                .setTemplateCode("SMS_305495744")
                //模板中的变量替换JSON串，如模板内容为"亲爱的${name}，您的验证码为${code}"时，此处的值为
                .setTemplateParam("{\"code\":" + code + "}");
        // 获取响应对象
        SendSmsResponse sendSmsResponse = client.sendSms(sendSmsRequest);
        // 响应包含服务端响应的 body 和 headers
        System.out.println(toJSONString(sendSmsResponse));
    }

    /**
     * 手机号一键登录
     *
     * @return 结果
     */
    @PostMapping("/phoneLogin")
    @ApiOperation("手机号一键登录")
    @Anonymous
    public R<UserIdToken> phoneLogin(String token, String phone) throws Exception {
        AjaxResult ajax = AjaxResult.success();
        YouMengToken youMengToken = new YouMengToken();
        CloseableHttpResponse response = youMengToken.getResponse(token, phone);
        // 取响应的结果
        int statusCode = response.getStatusLine().getStatusCode();
        // 打印响应结果
        if (statusCode == HttpStatus.SC_OK) {
            String resp = EntityUtils.toString(response.getEntity(), "utf-8");
            System.out.println("status:" + statusCode);
            System.out.println("result:" + resp);
        }
        HttpEntity entity = response.getEntity();
        String s = EntityUtils.toString(entity);//转换成字符串
        JSONObject datas = JSONObject.parseObject(s);//转换成JSON格式
        Boolean flag = (Boolean) datas.get("success");//获取返回数据状态，get获取的字段需要根据提供的返回值去获取
        //验证通过
        if (flag) {
            //判断是否存在该用户，存在则直接登录，不存在则自动注册后登录
            FhUser fhUser = new FhUser();
            fhUser.setPhone(phone);
            List<FhUser> fhUsers = iFhUserService.selectFhUserList(fhUser);
            //用户不存在
            if (fhUsers.isEmpty()) {
                //设置默认账户名，密码
                fhUser.setAccount("PhoneAcount" + phone);
                MD5 md5 = new MD5();
                fhUser.setPassword(md5.encode("phone"));
                int i = iFhUserService.insertFhUser(fhUser);
                if (i > 0) {
                    //向用户钓鱼信息表插入默认信息
//                    setFhMyInfo(i);
                    //注册成功，登录
                    R<UserIdToken> login = this.login(fhUser);
                    return login;
                }
            }
            //用户存在,直接登录
            else {
                R<UserIdToken> login = this.login(fhUsers.get(0));
                return login;
            }
        }

        return R.fail("登录失败");
    }

    /**
     * 微信号一键登录
     *
     * @return 结果
     */
    @PostMapping("/wxLogin")
    @ApiOperation("微信号一键登录")
    @Anonymous
    public R<UserIdToken> wxLogin(String openid) throws Exception {
        //判断是否存在该用户，存在则直接登录，不存在则自动注册后登录
        FhUser fhUser = new FhUser();
        fhUser.setWeixin(openid);
        List<FhUser> fhUsers = iFhUserService.selectFhUserList(fhUser);
        //设置默认账户名，密码
        fhUser.setAccount("WxAcount" + openid);
        MD5 md5 = new MD5();
        fhUser.setPassword(md5.encode("weixin"));
        //用户不存在
        if (fhUsers.isEmpty()) {
            int i = iFhUserService.insertFhUser(fhUser);
            if (i > 0) {
                //向用户钓鱼信息表插入默认信息
//                setFhMyInfo(i);
                //注册成功，登录
                return this.login(fhUser);
            }
        }
        //用户存在,直接登录
        else {
            return this.login(fhUsers.get(0));
        }
        return R.fail("登录失败");
    }

    /**
     * qq号一键登录
     *
     * @return 结果
     */
    @PostMapping("/qqLogin")
    @ApiOperation("qq号一键登录")
    @Anonymous
    public R<UserIdToken> qqLogin(String openid) throws Exception {
        //判断是否存在该用户，存在则直接登录，不存在则自动注册后登录
        FhUser fhUser = new FhUser();
        fhUser.setQq(openid);
        List<FhUser> fhUsers = iFhUserService.selectFhUserList(fhUser);
        //设置默认账户名，密码
        fhUser.setAccount("QqAcount" + openid);
        MD5 md5 = new MD5();
        fhUser.setPassword(md5.encode("qq"));
        //用户不存在
        if (fhUsers.isEmpty()) {
            int i = iFhUserService.insertFhUser(fhUser);
            if (i > 0) {
                //向用户钓鱼信息表插入默认信息
//                setFhMyInfo(i);
                //注册成功，登录
                return this.login(fhUser);
            }
        }
        //用户存在,直接登录
        else {
            return this.login(fhUsers.get(0));
        }
        return R.fail("登录失败");
    }

    //向用户钓鱼信息表插入默认信息
    //   public void setFhMyInfo(int i){
//        FhMyInfo fhMyInfo = new FhMyInfo();
//        Long user_id =(long) i;
//        fhMyInfo.setUserId(user_id);
//        fhMyInfo.setGrade(0L);
//        fhMyInfo.setFollowers(0L);
//        fhMyInfo.setFansNum(0L);
//        fhMyInfo.setPoint(0L);
//        fhMyInfo.setCoins(0L);
//        fhMyInfo.setFishTotal(0L);
//        fhMyInfo.setFishTypes(0L);
//        fhMyInfo.setAreaRank(0L);
//        fhMyInfo.setFriendRank(0L);
//        iFhMyInfoService.insertFhMyInfo(fhMyInfo);
    //   }

    /**
     * 重置密码
     *
     * @param fhUserDto 重置信息
     * @return 结果
     */
    @ApiOperation("重置密码")
    @Anonymous
    @PostMapping("/userResetPasswords")
    public R resetPasswords(FhUserDto fhUserDto) {
        String phone = fhUserDto.getPhone();
        String code = fhUserDto.getCode();
        //取出验证码
        ValueOperations<String, String> Value = rt.opsForValue();
        String old_yzm = Value.get(phone + "_yzm");
        if (old_yzm == null) {
            return R.fail("验证码不存在或者过期");
        } else if (old_yzm.equals(code)) {
            System.out.println("验证码正确");
            //根据手机号查询是否存在该用户
            FhUser fhUser1 = new FhUser();
            fhUser1.setPhone(fhUserDto.getPhone());
            List<FhUser> fhUsers = iFhUserService.selectFhUserList(fhUser1);
            if (fhUsers.isEmpty()) {
                return R.fail("该手机未注册账户，请注册");
            }
            //重置密码
            //加密密码
            MD5 md5 = new MD5();
            FhUser fhUser2 = fhUsers.get(0);
            fhUser2.setPassword(md5.encode(fhUserDto.getPassword()));
            int i = iFhUserService.updateFhUser(fhUser2);
            if (i >= 0) {
                return R.ok("重置密码成功");
            }
            return R.fail("重置密码失败");
        }
        return R.fail("验证码错误");
    }


    /**
     * 重置用户名
     *
     * @param fhUserDto 重置用户名
     * @return 结果
     */
    @ApiOperation("重置用户名")
    @Anonymous
    @PostMapping("/userResetAccount")
    public R resetAccount(FhUserDto fhUserDto) {
        String phone = fhUserDto.getPhone();
        String code = fhUserDto.getCode();
        //取出验证码
        ValueOperations<String, String> Value = rt.opsForValue();
        String old_yzm = Value.get(phone + "_yzm");
        if (old_yzm == null) {
            return R.fail("验证码不存在或者过期");
        } else if (old_yzm.equals(code)) {
            System.out.println("验证码正确");
            //根据手机号查询是否存在该用户
            FhUser fhUser1 = new FhUser();
            fhUser1.setPhone(fhUserDto.getPhone());
            List<FhUser> fhUsers = iFhUserService.selectFhUserList(fhUser1);
            if (fhUsers.isEmpty()) {
                return R.fail("该手机未注册账户，请注册");
            }
            //重置用户名
            FhUser fhUser2 = fhUsers.get(0);
            fhUser2.setAccount(fhUserDto.getAccount());
            int i = iFhUserService.updateFhUser(fhUser2);
            if (i >= 0) {
                return R.ok("重置用户成功");
            }
            return R.fail("重置用户名失败");
        }
        return R.fail("重置用户名错误");
    }


    /**
     * 获取管理员权限token
     */
    @ApiOperation("获取管理员权限token")
    @Anonymous
    @PostMapping("/getAdminToken")
    public String getAdminToken() throws IOException {
//       url实例 POST https://{host}/{org_name}/{app_name}/users
        String contentType = "application/json";
        String Accept = "application/json";
        // 构建请求 请求头
        String url = String.format("https://a1.easemob.com/%s/%s/%s?Content-Type=%s&Accept=%s",
                OrgName, appName, "token", contentType,Accept);
        // 请求体转换为 JSON 字符串
        HashMap<String, Object> body = new HashMap<>();
        body.put("grant_type", "client_credentials");
        body.put("client_id", ClientID);
        body.put("client_secret", clientSecret);
        body.put("ttl", 0L);
        MediaType JSON = MediaType.parse("application/json; charset=utf-8");
        String jsonBody = com.alibaba.fastjson2.JSON.toJSONString(body);
        RequestBody requestBody = RequestBody.create(JSON, jsonBody);
        // 发送请求并处理响应
        try {
            // 创建 OkHttp 客户端
            OkHttpClient client = new OkHttpClient();
            // 构建请求
            Request request = new Request.Builder()
                    .url(url)
                    .post(requestBody)
                    .build();
            Response response = client.newCall(request).execute();
            if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
            Headers responseHeaders = response.headers();
            for (int i = 0; i < responseHeaders.size(); i++) {
                System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
            }
            String responseBody = response.body().string();
            return responseBody;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    //向im注册用户
    public String registerImUser(Long userId) throws IOException {
        HashMap<String, Object> body = new HashMap<>();
        body.put("username", String.valueOf(userId));
        body.put("password", "123456");
        String users = imRequest(body, "users");
        return users;
    }

    //向im获取用户token
    public String getImUserToken(Long userId) throws IOException {
        HashMap<String, Object> body = new HashMap<>();
        body.put("grant_type", "inherit");
        body.put("username", String.valueOf(userId));
        body.put("autoCreateUser", true);
        body.put("ttl",0L);
        String users = imRequest(body, "token");
        return users;
    }


    /**
     * 基础环信im请求
     */
    public String imRequest(HashMap<String,Object> body, String apiUrl) throws IOException {
//       url实例 POST https://{host}/{org_name}/{app_name}/users
        String contentType = "application/json";
        String Accept = "application/json";
        // 构建请求 请求头
        String url = String.format("https://a1.easemob.com/%s/%s/%s?Content-Type=%s&Accept=%s&Authorization=%s",
                OrgName, appName, apiUrl, contentType,Accept,"Bearer "+AdminToken);
        //将map请求体转为RequestBody
        MediaType JSON = MediaType.parse("application/json; charset=utf-8");
        String jsonBody = com.alibaba.fastjson2.JSON.toJSONString(body);
        RequestBody requestBody = RequestBody.create(JSON, jsonBody);
        // 发送请求并处理响应
        try {
            // 创建 OkHttp 客户端
            OkHttpClient client = new OkHttpClient();
            // 构建请求
            Request request = new Request.Builder()
                    .url(url)
                    .post(requestBody)
                    .build();
            Response response = client.newCall(request).execute();
            if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
            Headers responseHeaders = response.headers();
            for (int i = 0; i < responseHeaders.size(); i++) {
                System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
            }
            String responseBody = response.body().string();
            return responseBody;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }







}
